#include "SceneNode.h"

#include "Mesh.h"
#include "OGLRender.h"

namespace Hope {
    SceneNode::SceneNode()
    {
        
    }

    SceneNode::SceneNode(const std::string &name, MeshPtr mesh) : m_mesh(mesh), m_name(name)
    {

    }

    SceneNode::~SceneNode()
    {

    }

    void SceneNode::Render()
	{
        OGLRender::Instance()->drawMesh(m_mesh);
	}

    void SceneNode::SetName(const std::string & name)
    {
        m_name = name;
    }

    void SceneNode::SetMesh(MeshPtr pMesh)
    {
        m_mesh = pMesh;
        m_meshDirty = true;
    }

	const glm::quat & SceneNode::GetLocalOrientation() const
	{
		return m_localOrientation;
	}

	void SceneNode::SetLocalOrientation(const glm::quat localOrientation)
	{
		m_localOrientation = localOrientation;
	}

	const glm::vec3 & SceneNode::GetLocalPosition() const
	{
		return m_localPosition;
	}

	void SceneNode::SetLocalPosition(const glm::vec3 localPosition)
	{
		m_localPosition = localPosition;
	}

	const glm::vec3 & SceneNode::GetLocalScale() const
	{
		return m_localScale;
	}

	void SceneNode::SetLoalScale(const glm::vec3 scale)
	{
		m_localScale = scale;
	}

	const glm::mat4 & SceneNode::GetLocalTransform() const
	{
		return m_localTransform;
	}

	void SceneNode::SetLocalTransform(const glm::mat4 & transform)
	{
		m_localTransform = transform;
	}

    void SceneNode::UpdateWorldTransform()
    {
    }

    const glm::mat4 & SceneNode::GetWorldTransform()
    {
        return glm::mat4();
    }

	void SceneNode::SetParent(SceneNode * parent)
	{
		m_parent = parent;
	}

	SceneNode * SceneNode::GetParent() const
	{
		return m_parent;
	}

	void SceneNode::AddChildNode(const SceneNodePtr &node)
	{
		m_children[node->GetName()] = node;
		node->SetParent(this);
	}

	uint32_t SceneNode::GetChildCount() const
	{
		return m_children.size();
	}

    const SceneNodePtr & SceneNode::GetChildNode(const std::string & name) const
	{
		auto it = m_children.find(name);
		if (it != m_children.end()) 
		{
			return it->second;
		}

		return NULL;
	}

	const SceneNodePtr & SceneNode::GetChildNode(uint32_t index) const
	{
		if (index >= m_children.size())
		{
			return NULL;
		}

		auto it = m_children.begin();
		for (uint32_t i = 0; i < index; ++i)
		{
			++it;
		}
		return it->second;
	}

	void SceneNode::RemoveChildNode(const SceneNodePtr &node)
	{
		auto it = m_children.begin();
		for (; it != m_children.end(); ++it)
		{
			if (it->second == node)
			{
				m_children.erase(it);
				node->SetParent(NULL);
				return;
			}
		}
	}

	void SceneNode::RemoveChildNode(const std::string & name)
	{
		auto it = m_children.find(name);
		if (it != m_children.end())
		{
			auto node = it->second;
			m_children.erase(it);
			node->SetParent(NULL);
			return;
		}
	}

	void SceneNode::SetVisible(bool flag)
	{
		m_visible = flag;
	}

	bool SceneNode::GetVisible() const
	{
		return m_visible;
	}

	const std::string & SceneNode::GetName()
	{
		return m_name;
	}

	void SceneNode::Update(float interval)
	{
	}

    void SceneNode::SetBoundingBox(const AABB & box)
    {
        m_localBoundingBox = box;
    }

    const AABB & SceneNode::GetLocalBoundingBox()
    {
        return m_localBoundingBox;
    }

    const AABB & SceneNode::GetWorldBoundingBox()
    {
        return m_worldBoundingBox;
    }

	void SceneNode::RemoveAllChildren()
	{
		auto it = m_children.begin();
		for (; it != m_children.end(); ++it)
		{
			it->second->SetParent(NULL);
		}

		m_children.clear();
	}





}